import { ContentEventer, ContentEventerData } from "@/us/event"
import { v4 as uuidv4 } from 'uuid';

export class UnsafeClient {

    constructor() {
        ContentEventer.initEvents();
        this.initEvents();
    }
    static init() {
        const client = new UnsafeClient()
        return client
    }
    private initEvents() {
        ContentEventer.addListener((msg) => {
            const originType = ContentEventer.getOriginType(msg.type);
            const func: any = Reflect.get(this, `_${originType}`);
            if (typeof func === 'function') {
                const res = func.call(this, msg.data);
                if (res instanceof Promise) {
                    res.then((resp: any) => {
                        const inMsg = { ...msg };
                        inMsg.data = resp;
                        inMsg.type = originType;
                        ContentEventer.send(inMsg, false);
                    })
                } else {
                    const inMsg = { ...msg };
                    inMsg.type = originType;
                    inMsg.data = res;
                    ContentEventer.send(inMsg, false);
                }
            }
        })

    }

    _addElement(arg: any) {
        const { tag, attributes } = arg;
        const el: HTMLElement = document.createElement(tag);
        if (typeof attributes === 'object') {
            for (const k in attributes) {
                Reflect.set(el, k, attributes[k]);
            }
        }
        el.dataset.id = 'id-' + uuidv4();
        document.body.appendChild(el);
        return new ContentEventerData('dom', `[data-id=${el.dataset.id}]`)
    }

    _addStyle(arg: any) {
        const { css } = arg;
        const el = document.createElement('style');
        el.textContent = css;
        document.head.appendChild(el);
        el.dataset.id = 'id-' + uuidv4();
        return new ContentEventerData('dom', `[data-id=${el.dataset.id}]`)
    }

    _unsafeWindow(key: string) {
        const val = Reflect.get(window, key);
        const valObj: UnsafeWindowProperty = {
            type: 'variable',
            name: key,
            data: val
        }
        if (val === undefined || val === null) {
            return new ContentEventerData('normal', valObj);
        } else if (val instanceof Element) {
            return new ContentEventerData('normal', valObj);
        } else if (typeof val === 'function') {
            return new ContentEventerData('normal', valObj);
        } else if (typeof val === 'string' || typeof val === 'number' || typeof val === 'bigint' || typeof val === 'boolean' || typeof val === 'symbol') {
            return new ContentEventerData('normal', valObj);
        } else if (typeof val === 'object') {
            return new ContentEventerData('normal', valObj);
        }
        return new ContentEventerData('normal', valObj);
    }

    _callWinodowFunc(data: any) {
        const { func, args } = data;
        const funcObj = Reflect.get(window, func);
        if (typeof funcObj === 'function') {
            return funcObj(...(args || []))
        }
    }

    _callObjectFunc(data: any) {
        const { obj, func, args } = data;
        const objIns = Reflect.get(window, obj);
        if (typeof objIns !== 'object') {
            return
        }
        const funcObj = Reflect.get(objIns, func);
        if (typeof funcObj === 'function') {
            return funcObj(...(args || []))
        }
    }

    _hello() {
        return new ContentEventerData('normal', 'hello,main script');
    }
}